home *** CD-ROM | disk | FTP | other *** search
/ SGI Developer Toolbox 6.1 / SGI Developer Toolbox 6.1 - Disc 4.iso / src / exampleCode / GLX / basics / pick.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-08-02  |  13.4 KB  |  486 lines

  1. /*
  2.  * Copyright 1992, 1993, 1994, Silicon Graphics, Inc.
  3.  * All Rights Reserved.
  4.  *
  5.  * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Silicon Graphics, Inc.;
  6.  * the contents of this file may not be disclosed to third parties, copied or
  7.  * duplicated in any form, in whole or in part, without the prior written
  8.  * permission of Silicon Graphics, Inc.
  9.  *
  10.  * RESTRICTED RIGHTS LEGEND:
  11.  * Use, duplication or disclosure by the Government is subject to restrictions
  12.  * as set forth in subdivision (c)(1)(ii) of the Rights in Technical Data
  13.  * and Computer Software clause at DFARS 252.227-7013, and/or in similar or
  14.  * successor clauses in the FAR, DOD or NASA FAR Supplement. Unpublished -
  15.  * rights reserved under the Copyright Laws of the United States.
  16.  */
  17. /** header ******************************************************************/
  18.  
  19. /*
  20. // $Id: pick2d.c,v 1.1 1994/02/11 18:49:16 brettb Exp $
  21. //
  22. // Title: pick2d.c -- demonstrate 2d picking in a mixed model program.
  23. // Keywords: IrisGL.Prod, IrisGL.Examples, Mixed, glx, picking
  24. // Viewable: No
  25. //
  26. // Description:
  27. //    This is a mixed model port of an IrisGL program which does 2d
  28. //    picking using the pick() function.
  29. //
  30. // Operation:
  31. //    Move the cursor over the blue edges or red vertices and click
  32. //    with the left mouse button to select things.  What is returned
  33. //    in the name buffer is displayed.  The pick size is 8 x 8 pixels.
  34. //    Depending on where you pick near a vertex you can get:
  35. //        - just the vertex;
  36. //        - the vertex and one adjoining edge;
  37. //        - or the vertex and both adjoining edges.
  38. //
  39. // Compilation:
  40. //    cc -float -prototypes -DFUNCPROTO -O pick2d.c -o pick2d \
  41. //    -s -lXirisw -lXm -lXt -lgl -lX11 -lm -lPW
  42. */
  43.  
  44. /** notes *******************************************************************/
  45. /** includes ****************************************************************/
  46.  
  47. #include <stdio.h>            /* printf, ... */
  48. #include <Xm/Xm.h>            /* for motif */
  49. #include <Xm/Form.h>            /* motif widget */
  50. #include <Xm/Frame.h>            /* motif widget */
  51. #include <Xm/PushB.h>            /* motif widget */
  52. #include <Xm/RowColumn.h>        /* motif widget */
  53. #include <Xm/Separator.h>        /* motif widget */
  54. #include <X11/Xirisw/GlxMDraw.h>    /* gl widget */
  55.  
  56. /** defines *****************************************************************/
  57.  
  58. /* limits */
  59. #define NAME_BUF_SIZE    50
  60.  
  61. /* colors */
  62. #define RGB_BLACK    0x00000000
  63. #define RGB_RED        0x000000FF
  64. #define RGB_WHITE    0x00FFFFFF
  65. #define RGB_BLUE    0x00FF0000
  66.  
  67. /* window values -- 2:1 */
  68. #define WIN_L        -0.5
  69. #define WIN_R        199.5
  70. #define WIN_B        -0.5
  71. #define WIN_T        99.5
  72.  
  73. /* pick group layout */
  74. #define POLY_GROUP    0
  75. #define EDGE_GROUP    1
  76. #define VERT_GROUP    2
  77.  
  78. /** prototypes **************************************************************/
  79.  
  80. /* setup */
  81. static void check_capabilities(void);
  82. static void install_colormaps(Widget top_level, Widget glw);
  83.  
  84. /* gl callbacks and support */
  85. static void gl_ginit_cb(Widget w, XtPointer appdat, XtPointer sysdat);
  86. static void gl_expose_cb(Widget w, XtPointer appdat, XtPointer sysdat);
  87. static void gl_resize_cb(Widget w, XtPointer appdat, XtPointer sysdat);
  88. static void gl_input_cb(Widget w, XtPointer appdat, XtPointer sysdat);
  89.  
  90. /* misc callbacks */
  91. static void quit_cb(Widget w, XtPointer appdat, XtPointer sysdat);
  92.  
  93. /* tests */
  94. static void pick_test(void);
  95.  
  96. /* drawing */
  97. static void draw_frame(void);
  98. static void draw_items(void);
  99. static void draw_poly(int poly_index);
  100. static void draw_hit_lists(short name_buffer[], long nhitlists);
  101.  
  102. /** typedefs ****************************************************************/
  103. /** variables ***************************************************************/
  104.  
  105. /*
  106. // mixed-model configuration:
  107. */
  108. static GLXconfig glx_config[] = {
  109.     {GLX_NORMAL, GLX_RGB, TRUE},
  110.     {GLX_NORMAL, GLX_DOUBLE, TRUE},
  111.     { 0, 0, 0 },
  112. };
  113.  
  114. /* picking results */
  115. static long nhitlists = 0;
  116. static short name_buffer[NAME_BUF_SIZE];
  117. static char *pick_group[] = {
  118.     "poly", "edge", "vert"
  119. };
  120.  
  121. /** functions ***************************************************************/
  122.  
  123. /*
  124. // main - program entry point.
  125. */
  126. void main(int argc, char *argv[])
  127. {
  128.     XtAppContext app_context;    /* application context */
  129.     Display *dsp;        /* display ref */
  130.     Widget app_shell;        /* first widget */
  131.     Widget form;        /* surrounds app */
  132.     Widget rowcol;        /* manages input buttons */
  133.     Widget button;        /* quit button */
  134.     Widget separator;        /* between input and output */
  135.     Widget frame;        /* to surround gl widget */
  136.     Widget glw;            /* can do gl rendering in this guy */
  137.     Arg args[15];        /* for name/value pairs */
  138.     int n;            /* reusable indices */
  139.  
  140.     /* make sure we can we do it */
  141.     check_capabilities();
  142.  
  143.     /* initialize toolkit, creating application shell */
  144.     n = 0;
  145.     XtSetArg(args[n], XmNtitle, "Pick Demo"); n++;
  146.     app_shell = XtAppInitialize(
  147.     &app_context, "Pick", NULL, 0, &argc, argv, NULL, args, n
  148.     );
  149.  
  150.     /* create container for app */
  151.     n = 0;
  152.     form = XmCreateForm(app_shell, "form", args, n);
  153.     XtManageChild(form);
  154.  
  155.     /* create the command area */
  156.     n = 0;
  157.     XtSetArg(args[n], XmNleftAttachment, XmATTACH_FORM); n++;
  158.     XtSetArg(args[n], XmNbottomAttachment, XmATTACH_FORM); n++;
  159.     XtSetArg(args[n], XmNtopAttachment, XmATTACH_FORM); n++;
  160.     XtSetArg(args[n], XmNorientation, XmVERTICAL); n++;
  161.     rowcol = XmCreateRowColumn(form, "rowcol", args, n);
  162.     XtManageChild(rowcol);
  163.  
  164.     /* create the command area buttons */
  165.     n = 0;
  166.     button = XmCreatePushButton(rowcol, "Quit", args, n);
  167.     XtAddCallback(button, XmNactivateCallback, quit_cb, NULL);
  168.     XtManageChild(button);
  169.  
  170.     /* create separator between command area and output area */
  171.     n = 0;
  172.     XtSetArg(args[n], XmNleftAttachment, XmATTACH_WIDGET); n++;
  173.     XtSetArg(args[n], XmNleftWidget, rowcol); n++;
  174.     XtSetArg(args[n], XmNbottomAttachment, XmATTACH_FORM); n++;
  175.     XtSetArg(args[n], XmNtopAttachment, XmATTACH_FORM); n++;
  176.     XtSetArg(args[n], XmNorientation, XmVERTICAL); n++;
  177.     separator = XmCreateSeparator(form, "separator", args, n);
  178.     XtManageChild(separator);
  179.  
  180.     /* create the output area */
  181.     /* create the frame */
  182.     n = 0;
  183.     XtSetArg(args[n], XmNleftAttachment, XmATTACH_WIDGET); n++;
  184.     XtSetArg(args[n], XmNleftWidget, separator); n++;
  185.     XtSetArg(args[n], XmNleftOffset, 5); n++;
  186.     XtSetArg(args[n], XmNrightAttachment, XmATTACH_FORM); n++;
  187.     XtSetArg(args[n], XmNrightOffset, 5); n++;
  188.     XtSetArg(args[n], XmNbottomAttachment, XmATTACH_FORM); n++;
  189.     XtSetArg(args[n], XmNbottomOffset, 5); n++;
  190.     XtSetArg(args[n], XmNtopAttachment, XmATTACH_FORM); n++;
  191.     XtSetArg(args[n], XmNtopOffset, 5); n++;
  192.     XtSetArg(args[n], XmNshadowThickness, 6); n++;
  193.     frame = XmCreateFrame(form, "frame", args, n);
  194.     XtManageChild(frame);
  195.  
  196.     /* create the gl widget */
  197.     n = 0;
  198.     XtSetArg(args[n], GlxNglxConfig, glx_config); n++;
  199.     XtSetArg(args[n], XmNborderWidth, 0); n++;
  200.     XtSetArg(args[n], XmNwidth, 800); n++;
  201.     XtSetArg(args[n], XmNheight, 400); n++;
  202.     glw = GlxCreateMDraw(frame, "glw", args, n);
  203.     XtManageChild(glw);
  204.     XtAddCallback(glw, GlxNexposeCallback, gl_expose_cb, 0);
  205.     XtAddCallback(glw, GlxNresizeCallback, gl_resize_cb, 0);
  206.     XtAddCallback(glw, GlxNginitCallback, gl_ginit_cb, 0);
  207.     XtAddCallback(glw, GlxNinputCallback, gl_input_cb, 0);
  208.  
  209.     /* realize the app, creating the actual x windows */
  210.     XtRealizeWidget(app_shell);
  211.     install_colormaps(app_shell, glw);
  212.  
  213.     /* enter the event loop */
  214.     XtAppMainLoop(app_context);
  215. }
  216.  
  217.  
  218. /*- support: setup ---------------------------------------------------------*/
  219. /*
  220. // check_capabilities - find out if the machine can do what we need.
  221. */
  222. static void check_capabilities(void)
  223. {
  224.     if (getgdesc(GD_BITS_NORM_DBL_RED) == 0) {
  225.     fprintf(stderr, "Double buffered RGB mode not available.\n");
  226.     exit(1);
  227.     }
  228. }
  229.  
  230.  
  231. /*
  232. // install_colormaps - let the window manager know about our colormaps.
  233. //
  234. // This has been generalized to handle any windows a gl widget might have.
  235. // It may not necessarily being using any of them.  
  236. */
  237. static void install_colormaps(Widget top_level, Widget glw)
  238. {
  239.     Window overlay_win, popup_win, underlay_win;
  240.     Window window[5];
  241.     int i;
  242.  
  243.     XtVaGetValues(
  244.     glw,
  245.     GlxNoverlayWindow, &overlay_win,
  246.     GlxNpopupWindow, &popup_win,
  247.     GlxNunderlayWindow, &underlay_win,
  248.     NULL
  249.     );
  250.     i = 0;
  251.     if (overlay_win)
  252.     window[i++] = overlay_win;
  253.     if (popup_win)
  254.     window[i++] = popup_win;
  255.     if (underlay_win)
  256.     window[i++] = underlay_win;
  257.     window[i++] = XtWindow(glw);
  258.     window[i++] = XtWindow(top_level);
  259.     XSetWMColormapWindows(XtDisplay(top_level), XtWindow(top_level), window, i);
  260. }
  261.  
  262.  
  263. /*- support: callbacks (gl widget) -----------------------------------------*/
  264. /*
  265. // gl_ginit_cb - perform any necessary graphics initialization.
  266. */
  267. static void gl_ginit_cb(Widget w, XtPointer appdat, XtPointer sysdat)
  268. {
  269.     GlxDrawCallbackStruct *glx = (GlxDrawCallbackStruct *) sysdat;
  270.  
  271.     GLXwinset(XtDisplay(w), XtWindow(w));
  272.     mmode(MVIEWING);
  273.     ortho2(WIN_L, WIN_R, WIN_B, WIN_T);
  274. }
  275.  
  276.  
  277. /*
  278. // gl_expose_cb - handle expose events for the gl widget.
  279. */
  280. static void gl_expose_cb(Widget w, XtPointer appdat, XtPointer sysdat)
  281. {
  282.     GlxDrawCallbackStruct *glx = (GlxDrawCallbackStruct *) sysdat;
  283.  
  284.     GLXwinset(XtDisplay(w), XtWindow(w));
  285.     draw_frame();
  286. }
  287.  
  288.  
  289. /*
  290. // gl_resize_cb - handle resize events for the gl widget.
  291. */
  292. static void gl_resize_cb(Widget w, XtPointer appdat, XtPointer sysdat)
  293. {
  294.     GlxDrawCallbackStruct *glx = (GlxDrawCallbackStruct *) sysdat;
  295.  
  296.     GLXwinset(XtDisplay(w), XtWindow(w));
  297.     viewport(0, glx->width-1, 0, glx->height-1);
  298. }
  299.  
  300.  
  301. /*
  302. // gl_input_cb - handle input from a gl window.
  303. */
  304. static void gl_input_cb(Widget w, XtPointer appdat, XtPointer sysdat)
  305. {
  306.     GlxDrawCallbackStruct *glx = (GlxDrawCallbackStruct *) sysdat;
  307.  
  308.     GLXwinset(XtDisplay(w), XtWindow(w));
  309.     switch (glx->event->type) {
  310.     case ButtonPress:
  311.     /* we will pick on the release */
  312.     break;
  313.     case ButtonRelease:
  314.     pick_test();
  315.     break;
  316.     }
  317. }
  318.  
  319.  
  320. /*- support: callbacks (misc) ----------------------------------------------*/
  321. /*
  322. // quit_cb - exit the application.
  323. */
  324. static void quit_cb(Widget w, XtPointer appdat, XtPointer sysdat)
  325. {
  326.     exit(0);
  327. }
  328.  
  329.  
  330. /*- support: picking and selecting -----------------------------------------*/
  331. /*
  332. // pick_test - try picking items which draw_items() displays.
  333. */
  334. static void pick_test(void)
  335. {
  336.     pushmatrix();
  337.     picksize(8, 8);
  338.     pick(name_buffer, NAME_BUF_SIZE);
  339.     ortho2(WIN_L, WIN_R, WIN_B, WIN_T);
  340.     initnames();
  341.     draw_items();
  342.     gflush();
  343.     nhitlists = endpick(name_buffer);
  344.     ortho2(WIN_L, WIN_R, WIN_B, WIN_T);
  345.     popmatrix();
  346.     draw_frame();
  347. }
  348.  
  349.  
  350. /*- support: drawing -------------------------------------------------------*/
  351. /*
  352. // draw_frame - render the next frame.
  353. */
  354. static void draw_frame(void)
  355. {
  356.     cpack(RGB_BLACK);
  357.     clear();
  358.     draw_items();
  359.     draw_hit_lists(name_buffer, nhitlists);
  360.     swapbuffers();
  361.     gflush();
  362. }
  363.  
  364.  
  365. /*
  366. // draw_items - draw a couple of polygons.
  367. */
  368. static void draw_items(void)
  369. {
  370.     loadname(0);
  371.     pushmatrix();
  372.     draw_poly(0);
  373.     translate(100.0, 0.0, 0.0);
  374.     draw_poly(1);
  375.     popmatrix();
  376. }
  377.  
  378.  
  379. /*
  380. // draw_poly - draw a single polygon.
  381. //
  382. // This names each polygon, each polygon edge, and each polygon vertex for
  383. // the purposes of picking.
  384. */
  385. static void draw_poly(int poly_index)
  386. {
  387.     static float poly_pt[][2] = {    /* describe pentagon */
  388.     {25.0, 25.0},
  389.     {75.0, 25.0},
  390.     {90.0, 60.0},
  391.     {50.0, 85.0},
  392.     {10.0, 60.0},
  393.     /**/
  394.     {25.0, 25.0},            /* wrap around to first point */
  395.     };
  396.     int i;                /* loop index */
  397.  
  398.     /* name polygon */
  399.     pushname(POLY_GROUP);        /* this is a polygon */
  400.     pushname(poly_index);        /* this is its name */
  401.  
  402.     /* draw edges in blue */
  403.     pushname(EDGE_GROUP);        /* these are edges */
  404.     linewidth(4);            /* make them all look big */
  405.     cpack(RGB_BLUE);
  406.     for (i=0; i<5; i++) {
  407.     pushname(i);            /* this is their subname: 0,1,2,... */
  408.     bgnline();
  409.         v2f(poly_pt[i+0]);
  410.         v2f(poly_pt[i+1]);
  411.     endline();
  412.     popname();
  413.     }
  414.     linewidth(1);
  415.     popname();
  416.  
  417.     /* draw vertices in red */
  418.     cpack(RGB_RED);
  419.     pushname(VERT_GROUP);        /* these are vertices */
  420.     for (i=0; i<5; i++) {
  421.     pushname(i);            /* this is their subname: 0,1,2,... */
  422.     circf(poly_pt[i][0], poly_pt[i][1], 2.0);
  423.     popname();
  424.     }
  425.     popname();
  426.  
  427.     popname();
  428.     popname();
  429. }
  430.  
  431.  
  432. /*
  433. // draw_hit_lists - display the hit lists for a polygon, interpreting
  434. // the hit list names so they having more meaning to our polygon.
  435. //
  436. // all of our returned names lists will be of the format:
  437. //    <poly_group, poly_sub_index, edge_group, edge_sub_index>
  438. //    or
  439. //    <poly_group, poly_sub_index, vert_group, vert_sub_index>
  440. //
  441. // thus all of our names lists should be of length 4.
  442. //
  443. */
  444. static void draw_hit_lists(short name_buffer[], long nhitlists)
  445. {
  446.     char str[50];        /* for building strings */
  447.     int list;            /* index of the current name list */
  448.     int nitems;            /* size of the current list */
  449.     int index;            /* scans uniformly through buffer[] */
  450.     int tx, ty, tdy;        /* simple text cursor */
  451.     int i;            /* index */
  452.  
  453.     tx = 70;
  454.     ty = 16;
  455.     tdy = 4;
  456.  
  457.     cpack(RGB_WHITE);
  458.     cmov2i(tx, ty);
  459.     sprintf(str, "%ld name list", nhitlists);
  460.     charstr(str);
  461.     if (nhitlists != 1)
  462.     charstr("s");
  463.     if (nhitlists > 0)
  464.     charstr(": ");
  465.     index = 0;
  466.     for (list=0; list<nhitlists; list++) {
  467.     ty -= tdy;            /* drop down one text line */
  468.     cmov2i(tx, ty);
  469.     sprintf(str, "list %d: ", list);
  470.     charstr(str);
  471.     nitems = name_buffer[index++];
  472.     index++;  /* skip... */
  473.     nitems--; /* ...loadname(0) */
  474.     for (i=0; i<nitems; i+=2) {
  475.         sprintf(str, "[%s %d] ",
  476.         pick_group[name_buffer[index]],
  477.         name_buffer[index+1]
  478.         );
  479.         charstr(str);
  480.         index += 2;
  481.     }
  482.     }
  483. }
  484.  
  485. /** eof *********************************************************************/
  486.